package rlib

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"sync"

	"github.com/golang/glog"
)

type ClusterConfig struct {
	Nodes    map[string]NodeConfig
	NodeName string
	filename string
	rdlock   sync.Mutex
}

var (
	ClusterConfigSingleton = &ClusterConfig{}
)

func LoadClusterConfig(filename string) (err error) {
	var (
		fByte []byte
	)
	f, err := os.Open(filename)
	if err != nil {
		return
	}
	defer f.Close()
	fByte, err = ioutil.ReadAll(f)
	if err != nil {
		return
	}
	err = json.Unmarshal(fByte, ClusterConfigSingleton)
	if err != nil {
		return
	}
	for k, v := range ClusterConfigSingleton.Nodes {
		glog.Infof("nodename=%s|addr=%s", k, v.Addr)
	}
	ClusterConfigSingleton.filename = filename
	return
}

func (ccf *ClusterConfig) SetNodeName(nodeName string) {
	ccf.rdlock.Lock()
	defer ccf.rdlock.Unlock()
	ClusterConfigSingleton.NodeName = nodeName
}

func (ccf *ClusterConfig) GetAddrByNodeName(nodeName string) string {
	ccf.rdlock.Lock()
	defer ccf.rdlock.Unlock()
	nc, ok := ClusterConfigSingleton.Nodes[nodeName]
	if !ok {
		return ""
	}
	return nc.Addr
}

func (ccf *ClusterConfig) GetClusterSize() int {
	ccf.rdlock.Lock()
	defer ccf.rdlock.Unlock()
	return len(ccf.Nodes)
}

func (ccf *ClusterConfig) AddNewNode(nodeConf NodeConfig) bool {
	ccf.rdlock.Lock()
	defer ccf.rdlock.Unlock()
	if _, ok := ccf.Nodes[nodeConf.NodeName]; ok {
		glog.Errorf("nodename %s is existed", nodeConf.NodeName)
		return false
	}
	ccf.Nodes[nodeConf.NodeName] = nodeConf
	err := ccf.LoadConfigToFile()
	if err != nil {
		glog.Error(err)
		return false
	}
	glog.Infof("node %s add ok, addr is %s", nodeConf.NodeName, nodeConf.Addr)
	return true
}

func (ccf *ClusterConfig) LoadConfigToFile() error {
	confByte, err := json.Marshal(ccf)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(ccf.filename, confByte, os.ModePerm)
}
